package org.example.rabbitmq.customer.handler;

import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.example.rabbitmq.common.message.MessageStruct;
import org.example.rabbitmq.common.message.Order;
import org.example.rabbitmq.common.util.MqUtil;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

/**
 * @author hzq
 * @date 2021/11/23 16:30
 */
@Slf4j
@Component
public class RabbitmqMessageHandler {

    /**
     * https://docs.spring.io/spring-amqp/docs/2.3.12/reference/html/#async-annotation-driven
     * <p>
     * 以下列表显示了您可以在侦听器端点中注入的主要元素：
     * <p>
     * 1、org.springframework.amqp.core.Message原始消息
     * 2、com.rabbitmq.client.Channel在其上接收该消息。
     * 3、org.springframework.messaging.Message代表进入AMQP消息。请注意，此消息包含自定义和标准标头（由 定义AmqpHeaders）。
     */
//    @RabbitListener(bindings = {
//            @QueueBinding(
//                    exchange = @Exchange(name = "direct.mode"),
//                    value = @Queue(name = "queue.direct.one", durable = "true", exclusive = "false", autoDelete = "false"),
//                    key = "queue.direct.one"
//            )
//    })
    @RabbitListener(queues = "queue.direct.one")
    public void receiveQueueDirectOneMessage(Message message, Channel channel) {

        log.info("queue.direct.one队列收到消息:{}", message);

        // 解析消息体
        MessageStruct messageStruct = MqUtil.parseMessage(message, MessageStruct.class);

        // 处理消息
        boolean handlerResult = handlerMessageStruct(messageStruct);

        // 确认消息
        MqUtil.basicAck(handlerResult, message, channel);
    }

    /*@RabbitListener(bindings = {
            @QueueBinding(
                    exchange = @Exchange(name = "direct.mode"),
                    value = @Queue(name = "two.queue.direct", durable = "true", exclusive = "false", autoDelete = "false"),
                    key = "two.queue.direct"
            )
    })*/
    @RabbitListener(queues = "two.queue.direct")
    public void receiveTwoQueueDirectMessage(Message message, Channel channel) {

        log.info("two.queue.direct队列收到消息:{}", message);

        // 解析消息体
        MessageStruct messageStruct = MqUtil.parseMessage(message, MessageStruct.class);

        // 处理消息
        boolean handlerResult = handlerMessageStruct(messageStruct);

        // 确认消息
        MqUtil.basicAck(handlerResult, message, channel);
    }

    /*@RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = "fanout.mode", type = ExchangeTypes.FANOUT),
            value = @Queue(name = "queue.fanout.one", durable = "true", exclusive = "false", autoDelete = "false")
    ))*/
    @RabbitListener(queues = "queue.fanout.one")
    public void receiveQueueFanoutOneMessage(Message message, Channel channel) {

        log.info("queue.fanout.one队列收到消息:{}", message);

        // 解析消息体
        MessageStruct messageStruct = MqUtil.parseMessage(message, MessageStruct.class);

        // 处理消息
        boolean handlerResult = handlerMessageStruct(messageStruct);

        // 确认消息
        MqUtil.basicAck(handlerResult, message, channel);
    }

    /* @RabbitListener(bindings = @QueueBinding(
             exchange = @Exchange(name = "fanout.mode", type = ExchangeTypes.FANOUT),
             value = @Queue(name = "fanout.queue.two", durable = "true", exclusive = "false", autoDelete = "false")
     ))*/
    @RabbitListener(queues = "fanout.queue.two")
    public void receiveFanoutQueueTwoMessage(Message message, Channel channel) {

        log.info("fanout.queue.two队列收到消息:{}", message);

        // 解析消息体
        MessageStruct messageStruct = MqUtil.parseMessage(message, MessageStruct.class);

        // 处理消息
        boolean handlerResult = handlerMessageStruct(messageStruct);

        // 确认消息
        MqUtil.basicAck(handlerResult, message, channel);
    }

    /* @RabbitListener(bindings = @QueueBinding(
             exchange = @Exchange(name = "topic.mode", type = ExchangeTypes.TOPIC),
             value = @Queue(name = "one.queue.topic", durable = "true", exclusive = "false", autoDelete = "false"),
             key = "*.queue.topic"
     ))*/
    @RabbitListener(queues = "one.queue.topic")
    public void receiveOneQueueTopicMessage(Message message, Channel channel) {

        log.info("one.queue.topic队列收到消息:{}", message);

        // 解析消息体
        MessageStruct messageStruct = MqUtil.parseMessage(message, MessageStruct.class);

        // 处理消息
        boolean handlerResult = handlerMessageStruct(messageStruct);

        // 确认消息
        MqUtil.basicAck(handlerResult, message, channel);
    }

    /*@RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(name = "topic.mode", type = ExchangeTypes.TOPIC),
            value = @Queue(name = "topic.queue.two", durable = "true", exclusive = "false", autoDelete = "false"),
            key = "topic.queue.*"
    ))*/
    @RabbitListener(queues = "topic.queue.two")
    public void receiveTopicQueueTwoMessage(Message message, Channel channel) {

        log.info("topic.queue.two队列收到消息:{}", message);

        // 解析消息体
        MessageStruct messageStruct = MqUtil.parseMessage(message, MessageStruct.class);

        // 处理消息
        boolean handlerResult = handlerMessageStruct(messageStruct);

        // 确认消息
        MqUtil.basicAck(handlerResult, message, channel);
    }

    @SneakyThrows
//    @RabbitListener(queues = "delay.queue")
    public void receiveDelayQueueMessage(Message message, Channel channel) {

        log.info("delay.queue队列收到消息:{}", message);

        // 解析消息体
        MessageStruct messageStruct = MqUtil.parseMessage(message, MessageStruct.class);

        // 处理消息
        boolean handlerResult = handlerMessageStruct(messageStruct);

        // 确认消息
//        MqUtil.basicAck(handlerResult, message, channel);
        channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
    }

//    @RabbitListener(queues = "custom.delay.queue")
    public void receiveCustomDelayQueueMessage(Message message, Channel channel) {

        log.info("custom.delay.queue队列收到消息:{}", message);

        // 解析消息体
        MessageStruct messageStruct = MqUtil.parseMessage(message, MessageStruct.class);

        // 处理消息
        boolean handlerResult = handlerMessageStruct(messageStruct);

        // 确认消息
        MqUtil.basicAck(handlerResult, message, channel);
    }

    /**
     * @param messageStruct 消息
     * @return 处理结果
     */
    boolean handlerMessageStruct(MessageStruct messageStruct) {

        // todo 处理消息

        log.info("处理消息:{}", messageStruct);

        return true;
    }

    /**
     * 处理订单返回处理结果
     *
     * @param order 订单
     * @return 结果
     */
    boolean handlerOrder(Order order) {

        // todo 处理订单

        log.info("处理订单:{}", order);

        return false;
    }

}
